package com.kolaxy.chat;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.util.Iterator;

public class ChatServer {


    //监听通道
    private ServerSocketChannel listenerChannel;
    //选择器
    private Selector selector;
    private static final int PORT = 9999;

    public ChatServer() {

        try {
            //初始化通道
            listenerChannel = ServerSocketChannel.open();

            //初始化选择器
            selector = Selector.open();

            //绑定端口
            listenerChannel.bind(new InetSocketAddress(PORT));

            //设定非阻塞
            listenerChannel.configureBlocking(false);

            //将选择器绑定到监听通道并监听accept事件
            listenerChannel.register(selector, SelectionKey.OP_ACCEPT);

            printInfo("Chat Server is ready...");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void printInfo(String s) {

        System.out.println("[" + LocalDateTime.now().toString() + "] -> " + s);
    }

    public void start() throws Exception {
        try {

            while (true) {
                if (selector.select(2000) == 0) {
                    System.out.println("没有连接  继续干其他事情");
                    continue;
                }

                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();

                    //连接进来
                    if (key.isAcceptable()) {
                        SocketChannel socketChannel = listenerChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                        System.out.println(socketChannel.getRemoteAddress().toString().substring(1) + "上线了");
                    }

                    //读取数据
                    if (key.isReadable()) {
                        readMsg(key);
                    }

                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //读取数据并广播出去
    private void readMsg(SelectionKey key) throws Exception {

        SocketChannel channel = (SocketChannel) key.channel();

        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        int count = channel.read(byteBuffer);

        if (count > 0) {
            String msg = new String(byteBuffer.array());
            printInfo(msg);

            //发广播
            broadCast(channel, msg);
        }


    }

    /**
     * 广播
     *
     * @param channel
     * @param msg
     * @throws Exception
     */
    private void broadCast(SocketChannel channel, String msg) throws Exception {

        System.out.println("服务器发送了广播...");

        for (SelectionKey key : selector.selectedKeys()) {
            SocketChannel socketChannel = (SocketChannel) key.channel();

            if (socketChannel instanceof SocketChannel && channel != socketChannel) {
                socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
            }

        }
    }

    public static void main(String[] args) throws Exception{
        new ChatServer().start();
    }
}


